﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace WindowsFormsApplication5
{
    public partial class Form1 : Form
    {
        //private static string ChatData = "";
        private List<Client> listClientSocket = new List<Client>();
        private System.Object lockThis = new System.Object();
        //array thread
        private Thread t;

        private ThreadRoom[] threadRoom = new ThreadRoom[20];
        // Thread signal.
        public ManualResetEvent allDone = new ManualResetEvent(false);
        public ManualResetEvent allDoneClient = new ManualResetEvent(false);

        public Form1()
        {
            InitializeComponent();
            t = new Thread(new ThreadStart(StartListenning));
            t.Start();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            //threadRoom[Global.curRoom] = new ThreadRoom(Global.curRoom);
            //Global.curRoom++;
        }

        public void StartListenning()
        {
            byte[] bytes = new Byte[StateObject.BufferSize];

            IPEndPoint endpoint = new IPEndPoint(IPAddress.Any, 13001);
            Socket listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            try
            {

                listener.Bind(endpoint);

                listener.Listen(10);

                while (true)
                {

                    allDone.Reset();

                    UIHelper.UIThread(listBox1, delegate
                    {
                        listBox1.Items.Add("Waiting for connection from client ......!");
                    });

                    listener.BeginAccept(new AsyncCallback(AcceptCallBack), listener);

                    allDone.WaitOne();
                }
            }
            catch (Exception e)
            {
                Console.WriteLine(e.ToString());
            }
            Console.WriteLine("\nPress ENTER to continue...");
            Console.Read();
        }

        public void AcceptCallBack(IAsyncResult ar)
        {
            allDone.Set();

            Socket listener = (Socket)ar.AsyncState;
            Socket handler = listener.EndAccept(ar);

            listClientSocket.Add(new Client(handler, 2));

            UIHelper.UIThread(listBox1, delegate
            {
                listBox1.Items.Add("Connected from: " + handler.RemoteEndPoint.ToString());
            });

            Thread clientThread = new Thread(new ParameterizedThreadStart(chatClientServer));
            clientThread.Start(handler);
        }

        private void chatClientServer(object clientsock)
        {
            while (true)
            {
                allDoneClient.Reset();

                Socket handler = (Socket)clientsock;
                StateObject state = new StateObject();
                state.workSocket = handler;
                handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReadCallBack), state);

                allDoneClient.WaitOne();
            }
        }

        public void ReadCallBack(IAsyncResult ar)
        {
            allDoneClient.Set();

            String content = String.Empty;

            StateObject state = (StateObject)ar.AsyncState;
            Socket handler = state.workSocket;

            int bytesRead = handler.EndReceive(ar);

            if (bytesRead > 0)
            {
                state.sb.Append(Encoding.UTF8.GetString(state.buffer, 0, bytesRead));
                content = state.sb.ToString();
                if (content.IndexOf("<EOF>") > -1)
                {
                    content = content.Replace("<EOF>", "");
                    if (!content.Equals("null"))
                    {
                        //save message
                        for (int i = 0; i < listClientSocket.Count; i++)
                        {
                            listClientSocket[i].message += content;
                        }
                        UIHelper.UIThread(listBox1, delegate
                        {
                            listBox1.Items.Add(state.sb.Replace("<EOF>", ""));
                        });

                        byte[] bytesData = Encoding.UTF8.GetBytes("null<EOF>");
                        handler.BeginSend(bytesData, 0, bytesData.Length, 0, new AsyncCallback(SendCallBack), handler);
                    }
                    else
                    {
                        sendBackToClient(handler);
                    }
                }
                else
                {
                    handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReadCallBack), state);
                }
            }
        }

        void sendBackToClient(Socket handler)
        {
            string data;
            for (int i = 0; i < listClientSocket.Count; i++)
            {
                if(listClientSocket[i].Sock == handler)
                {
                    if (listClientSocket[i].message != "")
                    {
                        data = listClientSocket[i].message + "<EOF>";
                        listClientSocket[i].message = "";
                    }
                    else //gui "null"
                    {
                        data = "null<EOF>";
                    }
                    byte[] bytesData = Encoding.UTF8.GetBytes(data);
                    handler.BeginSend(bytesData, 0, bytesData.Length, 0, new AsyncCallback(SendCallBack), handler);
                }
            }
        }

        private void SendCallBack(IAsyncResult ar)
        {
            Socket handler = (Socket)ar.AsyncState;

            int bytesSend = handler.EndSend(ar);
        }
        
    }
}
